package com.ruoyi.common.utils.file;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.*;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.config.OssConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;



/**
 * 阿里云OSS工具类
 * 
 * @author ruoyi
 */
@Component
public class OssUtils
{
    @Autowired
    private OSS ossClient;
    
    @Autowired
    private OssConfig ossConfig;
    
    /**
     * 上传文件
     * 
     * @param file 文件
     * @return 文件访问URL
     */
    public Map<String, Object> uploadFile(MultipartFile file)
    {
        try
        {
            return uploadFile(file.getOriginalFilename(), file.getInputStream());
        }
        catch (Exception e)
        {
            throw new ServiceException("文件上传失败: " + e.getMessage());
        }
    }
    
    /**
     * 上传文件
     * 
     * @param fileName 文件名
     * @param inputStream 文件流
     * @return 文件访问URL
     */
    public Map<String, Object> uploadFile(String fileName, InputStream inputStream)
    {
        try
        {
            Map<String, Object> map = new HashMap<>();
            // 生成文件路径
            String filePath = generateFilePath(fileName);
            
            // 创建上传请求
            PutObjectRequest putObjectRequest = new PutObjectRequest(ossConfig.getBucketName(), filePath, inputStream);
            
            // 设置文件元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType(getContentType(fileName));
            putObjectRequest.setMetadata(metadata);
            
            // 上传文件
            ossClient.putObject(putObjectRequest);
            
            // 返回文件访问URL
            String path = "https://" + ossConfig.getBucketName() + "." + ossConfig.getEndpoint() + "/" + filePath;
            map.put("url", getFileUrl(filePath));
            map.put("path",path);
            return map;

        }
        catch (Exception e)
        {
            throw new ServiceException("文件上传失败: " + e.getMessage());
        }
    }
    
    /**
     * 上传字节数组
     * 
     * @param fileName 文件名
     * @param bytes 字节数组
     * @return 文件访问URL
     */
    public String uploadFile(String fileName, byte[] bytes)
    {
        Map map = uploadFile(fileName, new ByteArrayInputStream(bytes));
        return map.get("url").toString();
    }
    
    /**
     * 删除文件
     *
     * @param fileName 文件名
     */
    public void deleteFile(String fileName)
    {
        try
        {
            // 从URL中提取文件路径
            String filePath = extractFilePathFromUrl(fileName);
            ossClient.deleteObject(ossConfig.getBucketName(),filePath);
        }
        catch (Exception e)
        {
            throw new ServiceException("文件删除失败: " + e.getMessage());
        }
    }

    /**
     * 下载文件
     * 
     * @param fileName 文件名
     * @return 文件流
     */
    public InputStream downloadFile(String fileName)
    {
        try
        {
            String filePath = extractFilePathFromUrl(fileName);
            GetObjectRequest getObjectRequest = new GetObjectRequest(ossConfig.getBucketName(), filePath);
            OSSObject ossObject = ossClient.getObject(getObjectRequest);
            return ossObject.getObjectContent();
        }
        catch (Exception e)
        {
            throw new ServiceException("文件下载失败: " + e.getMessage());
        }
    }
    
    /**
     * 生成文件路径
     * 
     * @param fileName 原始文件名
     * @return 文件路径
     */
    private String generateFilePath(String fileName)
    {
        // 获取文件扩展名
        String extension = "";
        if (StringUtils.isNotEmpty(fileName) && fileName.contains("."))
        {
            extension = fileName.substring(fileName.lastIndexOf("."));
        }
        
        // 生成新文件名：日期/UUID.扩展名
        String datePath = DateUtils.datePath();
        String uuid = UUID.randomUUID().toString().replace("-", "");
        
        return datePath + "/" + uuid + extension;
    }
    
    /**
     * 获取文件访问URL
     * 
     * @param filePath 文件路径
     * @return 访问URL
     */
    private String getFileUrl(String filePath)
    {
// 使用OSS Java SDK
        Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000); // 1小时
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(ossConfig.getBucketName(), filePath, HttpMethod.GET);
        request.setExpiration(expiration);
        URL signedUrl = ossClient.generatePresignedUrl(request);
        return signedUrl.toString();


        // 生成永久访问URL（如果bucket是公共读）
//        return "https://" + ossConfig.getBucketName() + "." + ossConfig.getEndpoint() + "/" + filePath;
    }
    
    /**
     * 从URL中提取文件路径
     * 
     * @param url 文件URL
     * @return 文件路径
     */
    private String extractFilePathFromUrl(String url)
    {
        if (url.startsWith("https://"))
        {
            // 从完整URL中提取路径
            String domain = "https://" + ossConfig.getBucketName() + "." + ossConfig.getEndpoint() + "/";
            if (url.startsWith(domain))
            {
                return url.substring(domain.length());
            }
        }
        // 如果不是完整URL，直接返回
        return url;
    }
    
    /**
     * 根据文件扩展名获取Content-Type
     * 
     * @param fileName 文件名
     * @return Content-Type
     */
    private String getContentType(String fileName)
    {
        if (StringUtils.isEmpty(fileName))
        {
            return "application/octet-stream";
        }
        
        String extension = fileName.toLowerCase();
        if (extension.endsWith(".jpg") || extension.endsWith(".jpeg"))
        {
            return "image/jpeg";
        }
        else if (extension.endsWith(".png"))
        {
            return "image/png";
        }
        else if (extension.endsWith(".gif"))
        {
            return "image/gif";
        }
        else if (extension.endsWith(".pdf"))
        {
            return "application/pdf";
        }
        else if (extension.endsWith(".doc"))
        {
            return "application/msword";
        }
        else if (extension.endsWith(".docx"))
        {
            return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
        }
        else if (extension.endsWith(".xls"))
        {
            return "application/vnd.ms-excel";
        }
        else if (extension.endsWith(".xlsx"))
        {
            return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        }
        else
        {
            return "application/octet-stream";
        }
    }
}
